﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using UnityEngine;

public static class GameObjectExtension
{
    public static T AddComponent<T>(this Component comp) where T: Component
    {
        return comp.gameObject.AddComponent<T>();
    }

    public static GameObject Clone(this GameObject obj)
    {
        return obj.transform.CloneGameObject<Transform>().gameObject;
    }

    public static GameObject CloneAsChild(this GameObject go, Transform parent, bool resetTransform = true)
    {
        return go.transform.CloneGameObjectAsChild<Transform>(parent, resetTransform).gameObject;
    }

    public static T CloneGameObject<T>(this T obj) where T: Component
    {
        return (T) UnityEngine.Object.Instantiate(obj, obj.transform.position, obj.transform.rotation);
    }

    public static T CloneGameObject<T>(this T obj, Vector3 position) where T: Component
    {
        return (T) UnityEngine.Object.Instantiate(obj, position, Quaternion.identity);
    }

    public static T CloneGameObjectAsChild<T>(this T comp, Transform parent, bool resetTransform = true) where T: Component
    {
        T local = UnityEngine.Object.Instantiate<T>(comp);
        local.transform.SetParent(parent);
        if (resetTransform)
        {
            local.transform.ResetTransform();
        }
        return local;
    }

    public static T CloneGameObjectAsChild<T>(this T comp, Transform parent, Vector3 position) where T: Component
    {
        T local = UnityEngine.Object.Instantiate<T>(comp);
        local.transform.position = position;
        local.transform.SetParent(parent);
        return local;
    }

    public static void CombineChildrenMeshes(this Transform tsm)
    {
        MeshFilter[] componentsInChildren = tsm.GetComponentsInChildren<MeshFilter>();
        MeshRenderer componentInChildren = tsm.GetComponentInChildren<MeshRenderer>();
        CombineInstance[] combine = new CombineInstance[componentsInChildren.Length];
        for (int i = 0; i < componentsInChildren.Length; i++)
        {
            combine[i].mesh = componentsInChildren[i].sharedMesh;
            combine[i].transform = componentsInChildren[i].transform.localToWorldMatrix;
            componentsInChildren[i].gameObject.SetActive(false);
        }
        GameObject go = new GameObject("CombinedMeshes") {
            transform = { parent = tsm },
            layer = componentInChildren.gameObject.layer
        };
        MeshFilter filter = go.AddComponent<MeshFilter>();
        filter.mesh = new Mesh();
        filter.mesh.CombineMeshes(combine);
        if (componentInChildren != null)
        {
            go.GetOrAddComponent<MeshRenderer>().sharedMaterial = componentInChildren.sharedMaterial;
        }
    }

    public static T CreateChildGameObject<T>(this Component obj) where T: Component
    {
        return obj.CreateChildGameObject<T>(null);
    }

    public static T CreateChildGameObject<T>(this GameObject obj) where T: Component
    {
        return obj.transform.CreateChildGameObject<T>(null);
    }

    public static GameObject CreateChildGameObject(this Component obj, string childName)
    {
        GameObject obj2 = new GameObject(childName);
        obj2.transform.SetParentAndResetTransform(obj.transform);
        return obj2;
    }

    public static T CreateChildGameObject<T>(this Component obj, string childName) where T: Component
    {
        if (childName == null)
        {
        }
        T local = new GameObject(typeof(T).Name).AddComponent<T>();
        local.transform.SetParentAndResetTransform(obj.transform);
        return local;
    }

    public static T CreateChildGameObject<T>(this GameObject obj, string childName) where T: Component
    {
        return obj.transform.CreateChildGameObject<T>(childName);
    }

    public static Transform FindChild(this Component obj, string childName)
    {
        return obj.transform.Find(childName);
    }

    public static T FindChild<T>(this Component obj, string childName) where T: Component
    {
        Transform transform = obj.FindChild(childName);
        return ((transform == null) ? null : transform.GetComponent<T>());
    }

    public static Transform FindChild(this GameObject obj, string childName)
    {
        return obj.transform.FindChild(childName);
    }

    public static T FindChild<T>(this GameObject obj, string childName) where T: Component
    {
        return obj.transform.FindChild<T>(childName);
    }

    [DebuggerHidden]
    public static IEnumerable<Transform> GetChildren(this Transform tsm)
    {
        return new <GetChildren>c__Iterator27 { tsm = tsm, <$>tsm = tsm, $PC = -2 };
    }

    public static T GetComponentInRoot<T>(this Component comp)
    {
        return comp.transform.root.GetComponent<T>();
    }

    public static T GetComponentInRoot<T>(this GameObject go)
    {
        return go.transform.root.GetComponent<T>();
    }

    public static Component GetComponentInRoot(this Component comp, System.Type type)
    {
        return comp.transform.root.GetComponent(type);
    }

    public static Component[] GetComponentsInRoot(this Component comp, System.Type type)
    {
        return comp.transform.root.GetComponents(type);
    }

    public static T GetOrAddComponent<T>(this Component comp) where T: Component
    {
        return comp.gameObject.GetOrAddComponent<T>();
    }

    public static T GetOrAddComponent<T>(this GameObject go) where T: Component
    {
        if (go == null)
        {
            return null;
        }
        T component = go.GetComponent<T>();
        if (component == null)
        {
            component = go.AddComponent<T>();
        }
        return component;
    }

    public static string GetPathInHierarchy(this Transform tsm)
    {
        return tsm.GetPathInHierarchy("/");
    }

    public static string GetPathInHierarchy(this Transform tsm, string separator)
    {
        return tsm.GetPathInHierarchy(separator, null);
    }

    public static string GetPathInHierarchy(this Transform tsm, string separator, Transform manuallyRoot)
    {
        string name = tsm.name;
        while (((tsm != null) && (tsm != manuallyRoot)) && (tsm.parent != null))
        {
            tsm = tsm.parent;
            name = tsm.name + separator + name;
        }
        return name;
    }

    public static GameObject GetRoot(this Component comp)
    {
        return ((comp == null) ? null : comp.transform.root.gameObject);
    }

    public static GameObject GetRoot(this GameObject go)
    {
        return ((go == null) ? null : go.transform.root.gameObject);
    }

    public static Rect GetWorldRect(this RectTransform tsm)
    {
        Vector3 vector = tsm.TransformPoint((Vector3) tsm.rect.min);
        Vector3 vector2 = tsm.TransformPoint((Vector3) tsm.rect.max);
        return new Rect { min = vector, max = vector2 };
    }

    public static RaycastHit MoveWithCollision(this Transform tsm, Vector3 position, int layerMask = -1)
    {
        RaycastHit hit;
        Vector3 vector3 = position - tsm.position;
        Vector3 vector2 = (Vector3) (vector3.normalized * 0.1f);
        Physics.Linecast(tsm.position - vector2, position, out hit);
        if (Physics.Linecast(tsm.position - vector2, position, out hit, layerMask))
        {
            tsm.position = hit.point;
            return hit;
        }
        tsm.position = position;
        return hit;
    }

    public static void ResetTransform(this GameObject go)
    {
        go.transform.ResetTransform();
    }

    public static void ResetTransform(this Transform tsm)
    {
        tsm.localPosition = Vector3.zero;
        tsm.localEulerAngles = Vector3.zero;
        tsm.localScale = Vector3.one;
    }

    public static void SetActive(this Transform tsm, bool value)
    {
        tsm.gameObject.SetActive(value);
    }

    public static void SetParentAndResetTransform(this GameObject go, GameObject parentGO)
    {
        go.transform.SetParent(parentGO.transform);
        go.transform.ResetTransform();
    }

    public static void SetParentAndResetTransform(this Transform tsm, GameObject parentGO)
    {
        tsm.SetParent(parentGO.transform);
        tsm.ResetTransform();
    }

    public static void SetParentAndResetTransform(this Transform tsm, Transform parent)
    {
        tsm.SetParent(parent);
        tsm.ResetTransform();
    }

    public static void SortByDistance<T>(this List<T> gos, Vector3 targetPos) where T: Component
    {
        <SortByDistance>c__AnonStorey89<T> storey = new <SortByDistance>c__AnonStorey89<T> {
            targetPos = targetPos
        };
        gos.Sort(new Comparison<T>(storey.<>m__185));
    }

    [CompilerGenerated]
    private sealed class <GetChildren>c__Iterator27 : IDisposable, IEnumerator, IEnumerable, IEnumerable<Transform>, IEnumerator<Transform>
    {
        internal Transform $current;
        internal int $PC;
        internal Transform <$>tsm;
        internal int <i>__0;
        internal Transform tsm;

        [DebuggerHidden]
        public void Dispose()
        {
            this.$PC = -1;
        }

        public bool MoveNext()
        {
            uint num = (uint) this.$PC;
            this.$PC = -1;
            switch (num)
            {
                case 0:
                    this.<i>__0 = 0;
                    break;

                case 1:
                    this.<i>__0++;
                    break;

                default:
                    goto Label_007B;
            }
            if (this.<i>__0 < this.tsm.childCount)
            {
                this.$current = this.tsm.GetChild(this.<i>__0);
                this.$PC = 1;
                return true;
            }
            this.$PC = -1;
        Label_007B:
            return false;
        }

        [DebuggerHidden]
        public void Reset()
        {
            throw new NotSupportedException();
        }

        [DebuggerHidden]
        IEnumerator<Transform> IEnumerable<Transform>.GetEnumerator()
        {
            if (Interlocked.CompareExchange(ref this.$PC, 0, -2) == -2)
            {
                return this;
            }
            return new GameObjectExtension.<GetChildren>c__Iterator27 { tsm = this.<$>tsm };
        }

        [DebuggerHidden]
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.System.Collections.Generic.IEnumerable<UnityEngine.Transform>.GetEnumerator();
        }

        Transform IEnumerator<Transform>.Current
        {
            [DebuggerHidden]
            get
            {
                return this.$current;
            }
        }

        object IEnumerator.Current
        {
            [DebuggerHidden]
            get
            {
                return this.$current;
            }
        }
    }

    [CompilerGenerated]
    private sealed class <SortByDistance>c__AnonStorey89<T> where T: Component
    {
        internal Vector3 targetPos;

        internal int <>m__185(T a, T b)
        {
            return Vector3.Distance(this.targetPos, a.transform.position).CompareTo(Vector3.Distance(this.targetPos, b.transform.position));
        }
    }
}

